#include "stdafx.h"
#include "CameraController.h"

#include "GraphicsSystem.h"

#include "OgreCamera.h"
#include "OgreRenderWindow.h"
#include <windows.h>

using namespace OgreModel;

namespace OgreModel
{
    CameraController::CameraController( GraphicsSystem *graphicsSystem, bool useSceneNode ) :
#if OGRE_USE_SDL2
        mUseSceneNode( useSceneNode ),
        mSpeedMofifier( false ),
        m_fAngleLook( 0 ),
        m_fAngleUp( 0 ),
        mCameraBaseSpeed( 10 ),
        mCameraSpeedBoost( 5 ),
        mGraphicsSystem( graphicsSystem )
#else
		mUseSceneNode(useSceneNode),
		m_fSpeed(100.0),
		m_fAngleLook(0),
		m_fAngleUp(0),
		m_pGraphicsSystem(graphicsSystem),
		m_isNeedRotate(false),
		m_isNeedMove(false),
		m_TimeLast(0),
		m_TimeLastBefore(0)
#endif
    {
#if OGRE_USE_SDL2
		memset(mWASD, 0, sizeof(mWASD));
        memset( mSlideUpDown, 0, sizeof(mSlideUpDown) );
#else

		m_vMoveRelValue = Ogre::Vector3(0, 0, 0);
		m_vMoveABSValue = Ogre::Vector3(0, 0, 0);
#endif
	}
#if OGRE_USE_SDL2
	//-----------------------------------------------------------------------------------
	void CameraController::update(float timeSinceLast)
	{
		Ogre::Camera *camera = mGraphicsSystem->getCamera();

		if (m_fAngleLook || m_fAngleUp)
		{
			if (mUseSceneNode)
			{
				Ogre::Node *cameraNode = camera->getParentNode();

				// Update now as yaw needs the derived orientation.
				cameraNode->_getFullTransformUpdated();
				cameraNode->yaw(Ogre::Radian(m_fAngleLook), Ogre::Node::TS_WORLD);
				cameraNode->pitch(Ogre::Radian(m_fAngleUp));
			}
			else
			{
				camera->yaw(Ogre::Radian(m_fAngleLook));
				camera->pitch(Ogre::Radian(m_fAngleUp));
			}

			m_fAngleLook = 0.0f;
			m_fAngleUp = 0.0f;
		}

		int camMovementZ = mWASD[2] - mWASD[0];
		int camMovementX = mWASD[3] - mWASD[1];
		int slideUpDown = mSlideUpDown[0] - mSlideUpDown[1];

		if (camMovementZ || camMovementX || slideUpDown)
		{
			Ogre::Vector3 camMovementDir(camMovementX, slideUpDown, camMovementZ);
			camMovementDir.normalise();
			camMovementDir *= timeSinceLast * mCameraBaseSpeed * (1 + mSpeedMofifier * mCameraSpeedBoost);

			if (mUseSceneNode)
			{
				Ogre::Node *cameraNode = camera->getParentNode();
				cameraNode->translate(camMovementDir, Ogre::Node::TS_LOCAL);
			}
			else
			{
				camera->moveRelative(camMovementDir);
			}
		}
	}
	//-----------------------------------------------------------------------------------
	bool CameraController::keyPressed(const SDL_KeyboardEvent &arg)
	{
		if (arg.keysym.sym == SDLK_LSHIFT)
			mSpeedMofifier = true;

		if (arg.keysym.sym == SDLK_w)
			mWASD[0] = true;
		else if (arg.keysym.sym == SDLK_a)
			mWASD[1] = true;
		else if (arg.keysym.sym == SDLK_s)
			mWASD[2] = true;
		else if (arg.keysym.sym == SDLK_d)
			mWASD[3] = true;
		else if (arg.keysym.sym == SDLK_PAGEUP)
			mSlideUpDown[0] = true;
		else if (arg.keysym.sym == SDLK_PAGEDOWN)
			mSlideUpDown[1] = true;
		else
			return false;

		return true;
	}
	//-----------------------------------------------------------------------------------
	bool CameraController::keyReleased(const SDL_KeyboardEvent &arg)
	{
		if (arg.keysym.sym == SDLK_LSHIFT)
			mSpeedMofifier = false;

		if (arg.keysym.sym == SDLK_w)
			mWASD[0] = false;
		else if (arg.keysym.sym == SDLK_a)
			mWASD[1] = false;
		else if (arg.keysym.sym == SDLK_s)
			mWASD[2] = false;
		else if (arg.keysym.sym == SDLK_d)
			mWASD[3] = false;
		else if (arg.keysym.sym == SDLK_PAGEUP)
			mSlideUpDown[0] = false;
		else if (arg.keysym.sym == SDLK_PAGEDOWN)
			mSlideUpDown[1] = false;
		else
			return false;

		return true;
	}
	//-----------------------------------------------------------------------------------
	void CameraController::mouseMoved(const SDL_Event &arg)
	{
		float width = mGraphicsSystem->getRenderWindow()->getWidth();
		float height = mGraphicsSystem->getRenderWindow()->getHeight();

		m_fAngleLook += -arg.motion.xrel / width;
		m_fAngleUp += -arg.motion.yrel / height;
	}
#else


	void CameraController::update(float timeSinceLast)
	{
		Ogre::Camera *camera = m_pGraphicsSystem->getCamera();
		m_TimeLast += timeSinceLast;
		if (m_isNeedRotate)
		{
			if (m_fAngleLook != 0 || m_fAngleUp != 0)
			{
				Ogre::Vector3 dir = camera->getDirection();
				Ogre::Vector3 up = Ogre::Vector3(0, 0, 1);

				dir = dir.crossProduct(up);

			//	Rotate(m_fAngleLook, dir);
			//	Rotate(m_fAngleLook, up);
				//camera->rotate(dir, Ogre::Radian(m_fAngleLook));
				//camera->rotate(up, Ogre::Radian(m_fAngleUp));
				camera->yaw(Ogre::Radian(m_fAngleUp));
				camera->pitch(Ogre::Radian(m_fAngleLook));

				/*Ogre::Vector3 direction = camera->getDirection();
				up = Ogre::Vector3(0, 0, -1);
				Ogre::Vector3 right = direction.crossProduct(up);
				Ogre::Quaternion cameraOrientation(right, up, direction);
				camera->setOrientation(cameraOrientation);*/
				//if (mUseSceneNode)
				//{
				//	Ogre::Node *cameraNode = camera->getParentNode();

				//	// Update now as yaw needs the derived orientation.
				//	cameraNode->_getFullTransformUpdated();
				//	cameraNode->yaw(Ogre::Radian(mCameraYaw), Ogre::Node::TS_WORLD);
				//	cameraNode->pitch(Ogre::Radian(mCameraPitch));
				//}
				//else
				//{
				//	camera->yaw(Ogre::Radian(mCameraYaw));
				//	camera->pitch(Ogre::Radian(mCameraPitch));
				//}

			/*	Ogre::Vector3 direction = camera->getDirection();
				up = Ogre::Vector3(0, 0, -1);
				Ogre::Vector3 right = direction.crossProduct(up);
				Ogre::Quaternion cameraOrientation(right, up, direction);
				camera->setOrientation(cameraOrientation);*/
				m_fAngleLook = 0.0f;
				m_fAngleUp = 0.0f;
			}
		}


		Ogre::Vector3 camMovementDir = m_vMoveABSValue;
		if (m_vMoveABSValue.length() > 0)
		{
			m_vMoveABSValue = Ogre::Vector3(0, 0, 0);
		}
		if (m_vMoveRelValue.length() > 0)
		{
			camMovementDir += m_vMoveRelValue*m_fSpeed*timeSinceLast;
			// camMovementDir.normalise();
			// camMovementDir *= timeSinceLast * 10.0f * (1 + mSpeedMofifier * 5);
			m_vMoveRelValue = Ogre::Vector3(0, 0, 0);
		}

		if (mUseSceneNode)
		{
			Ogre::Node *cameraNode = camera->getParentNode();
			cameraNode->translate(camMovementDir, Ogre::Node::TS_LOCAL);
		}
		else
		{
			camera->moveRelative(camMovementDir);
		}
	}


bool CameraController::VKKeybordPressed(const std::map<int, bool> & vk_Key)
{
	static clock_t timeCal = 0;
	bool ret = true;
	if (vk_Key.at('S') || vk_Key.at(VK_DOWN))
	{
		m_vMoveRelValue.z += 1;
	}
	if (vk_Key.at('W') || vk_Key.at(VK_UP))
	{
		m_vMoveRelValue.z -= 1;
	}
	if (vk_Key.at('A') || vk_Key.at(VK_LEFT))
	{
		m_vMoveRelValue.x -= 1;
	}
	if (vk_Key.at('D') || vk_Key.at(VK_RIGHT))
	{
		m_vMoveRelValue.x += 1;
	}
	if (vk_Key.at(VK_OEM_COMMA))
	{
		if ((clock() - timeCal) > CLOCKS_PER_SEC / 2)
		{
			timeCal = clock();
			m_fSpeed /= 1.1;
		}
	}
	if (vk_Key.at(VK_OEM_PERIOD))
	{
		if ((clock() - timeCal) > CLOCKS_PER_SEC / 2)
		{
			timeCal = clock();
			m_fSpeed *= 1.1;
		}
	}
	return ret;
}
bool CameraController::VKMousePressed(const std::map<int, bool> & vk_Key)
{
	if (vk_Key.at(VK_MBUTTON) && !m_isNeedRotate)
	{
		m_fAngleUp = 0;
		m_fAngleLook = 0;
		m_isNeedRotate = true;
		m_pntBefore = QCursor::pos();
	}
	else if(!vk_Key.at(VK_MBUTTON))
	{
		m_isNeedRotate = false;
	}
	if (vk_Key.at(VK_LBUTTON) && !m_isNeedMove)
	{
		m_pntBefore = QCursor::pos();
		m_isNeedMove = true;
	}
	else if(!vk_Key.at(VK_LBUTTON))
	{
		m_isNeedMove = false;
	}

	if (m_isNeedRotate)
	{
		float width = m_pGraphicsSystem->getRenderWindow()->getWidth();
		float height = m_pGraphicsSystem->getRenderWindow()->getHeight();
		QPoint pntNow = QCursor::pos();
		m_fAngleUp += (pntNow.x() - m_pntBefore.x())*2*3.1415 / (width);
		m_fAngleLook += (pntNow.y() - m_pntBefore.y()) * 2 * 3.1415 / (height);
		m_pntBefore = pntNow;
	}
	if (m_isNeedMove)
	{
		QPoint pntNow = QCursor::pos();
		m_vMoveABSValue.x += 0.1*(m_pntBefore.x() - pntNow.x());
		m_vMoveABSValue.y -= 0.1*(m_pntBefore.y() - pntNow.y());
		m_pntBefore = pntNow;
	}

	return true;
}

#endif

}
